package com.yoj.judgeservice.codesandbox.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.yoj.judgeservice.codesandbox.CodeSandbox;
import com.yoj.judgeservice.config.CodeSandboxProperties;
import com.yoj.common.common.ResultCodeEnum;
import com.yoj.common.exception.BusinessException;
import com.yoj.common.utils.SignUtils;
import com.yoj.model.codesandbox.ExecuteCodeRequest;
import com.yoj.model.codesandbox.ExecuteCodeResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 远程代码沙箱（实际调用接口的沙箱）
 */
@Slf4j
@Component
public class RemoteCodeSandbox implements CodeSandbox {

    @Resource
    private CodeSandboxProperties codeSandboxProperties;

    /**
     * 请求头的哈希映射，构造请求头
     * @param body 请求体内容
     * @return 包含请求头参数的哈希映射
     */
    private Map<String, String> getHeaderMap(String body) {
        // 创建一个新的 HashMap 对象
        Map<String, String> hashMap = new HashMap<>();
        hashMap.put("accessKey", codeSandboxProperties.getAccessKey());
        // 不能直接发送密钥
        // hashMap.put("secretKey", secretKey);
        // 生成随机数，包含20个随机数字的字符串
        hashMap.put("nonce", RandomUtil.randomNumbers(20));
        // 当前时间戳，单位毫秒，转换为字符串
        hashMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
        // 生成签名
        hashMap.put("sign", SignUtils.genSign(body, codeSandboxProperties.getSecretKey()));
        // 请求体内容
        // 解决参数乱码问题
        try {
            body = URLEncoder.encode(body, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        hashMap.put("body", body);
        return hashMap;
    }

    public ExecuteCodeResponse executeCode(ExecuteCodeRequest executeCodeRequest) {
        log.info("调用远程代码沙箱");
        String url = codeSandboxProperties.getUrl() + "/executeCode";
        String bodyJson = JSONUtil.toJsonStr(executeCodeRequest);
        String responseStr = HttpRequest.post(url)
                .addHeaders(getHeaderMap(bodyJson))
                .body(bodyJson)
                .execute()
                .body();
        if (StringUtils.isBlank(responseStr)) {
            throw new BusinessException(ResultCodeEnum.API_REQUEST_ERROR, "代码沙箱远程接口调用错误：" + responseStr);
        }
        return JSONUtil.toBean(responseStr, ExecuteCodeResponse.class);
    }
}